import argparse
import subprocess

TEMPORARY_PLAY_FILE = 'play.yml'
INVENTORY_FILE = 'inventory.yml'

class AnsiblePlaybookGenerator:
    '''
    ansible 剧本生成类
    '''
    def __init__(self):
        pass

    def generate_playbook(self, role, hosts, gather_facts='no', **kwargs):
        playbook = {
            'hosts': hosts,
            'remote_user': 'root',
            'gather_facts': gather_facts,
            'roles': [
                {
                    'role': role,
                    'vars': [{key: value} for key, value in kwargs.items() if value is not None]
                }
            ]
        }
        return playbook


    def generate_playbook_file(self, playbook_dict, file_name='play.yml'):
        with open(file_name, 'w') as playbook_file:
            playbook_file.write(f'- hosts: {playbook_dict["hosts"]}\n')
            playbook_file.write(f'  remote_user: {playbook_dict["remote_user"]}\n')
            playbook_file.write(f'  gather_facts: {playbook_dict["gather_facts"]}\n')
            playbook_file.write('  roles:\n')
            playbook_file.write('    - role: ' + playbook_dict['roles'][0]['role'] + '\n')
            playbook_file.write('      vars:\n')
            for var in playbook_dict['roles'][0]['vars']:
                for key, value in var.items():
                    playbook_file.write(f'        - {key}: {value}\n')
    
    def run_playbook(self, inventory):
        subprocess.run(['ansible-playbook', '-i', inventory, '--vault-id', 'root@./ansible-valut-pw-file', TEMPORARY_PLAY_FILE, '-f', '10', '-b'])




class CommandTool:

    def __init__(self):
        self.parser = argparse.ArgumentParser(description='自动化安装Linux软件')
        self.subparsers = self.parser.add_subparsers(dest='module', help='可用模块')
        
        # 增加模块
        self._add_config_repo_subparser()
        self._add_change_hosts_subparser()
        self._add_distribute_file_subparser()
        self._add_download_file_subparser()
        self._add_firewall_whitelist_subparser()
        self._add_install_chrony_subparser()
        self._add_install_docker_subparser()
        self._add_install_firewalld_subparser()
        self._add_install_common_tools_subparser()
        self._add_install_repo_subparser()
        self._add_install_repo_manager_subparser()
        self._add_install_mydumper_subparser()
        self._add_install_ntpdate_subparser()
        self._add_install_nginx_subparser()
        # self._add_config_yumrepo_subparser()
        # self._add_test_subparser()
        # self._add_test_inner_subparser()
        self._add_sync_time_subparser()
        # 增加jdk
        self._add_install_jdk8_subparser()

        self.generator = AnsiblePlaybookGenerator()

    def _add_download_file_subparser(self):
        sub_parser = self.subparsers.add_parser("download-file", help='从远程主机下载文件到本地，默认下载history操作日志')
        sub_parser.add_argument('hosts', help='资产主机组-资产清单中维护')
        sub_parser.add_argument('--inventory', default=INVENTORY_FILE, help='指定inventory文件路径')
        sub_parser.add_argument('--download_file_path', help='要下载的文件路径，默认为家目录下的.bash_history')

    def _add_distribute_file_subparser(self):
        sub_parser = self.subparsers.add_parser("distribute-file", help='上传文件到远程主机')
        sub_parser.add_argument('hosts', help='资产主机组-资产清单中维护')
        sub_parser.add_argument('--inventory', default=INVENTORY_FILE, help='指定inventory文件路径')
        sub_parser.add_argument('--upload_path', help='本机要上传的文件路径，默认为roles/distribute-file/file/*')
        sub_parser.add_argument('--remote_host_path', help='要存放到远程主机的路径，默认为/opt/upload')



    def _add_change_hosts_subparser(self):
        sub_parser = self.subparsers.add_parser("change-hosts", help='添加主机hosts模块，默认格式为 域名前缀+IP匹配+域名后缀 ')
        sub_parser.add_argument('hosts', help='资产主机组-资产清单中维护')
        sub_parser.add_argument('--inventory', default=INVENTORY_FILE, help='指定inventory文件路径')
        sub_parser.add_argument('--hostname_prefix', help='修改通用域名前缀')
        sub_parser.add_argument('--hostname_suffix', help='修改通用域名后缀')
        sub_parser.add_argument('--hostsname_matching_rule', help='修改通用IP匹配规则，默认为"{{ item.split(\'.\')[-1] }}"')
    def _add_install_chrony_subparser(self):
        sub_parser = self.subparsers.add_parser("install-chrony", help='安装chrony模块')
        sub_parser.add_argument('hosts', help='资产主机组-资产清单中维护')
        sub_parser.add_argument('--inventory', default=INVENTORY_FILE, help='指定inventory文件路径')

    def _add_install_ntpdate_subparser(self):
        sub_parser = self.subparsers.add_parser("install-ntpdate", help='安装ntpdate模块')
        sub_parser.add_argument('hosts', help='资产主机组-资产清单中维护')
        sub_parser.add_argument('--inventory', default=INVENTORY_FILE, help='指定inventory文件路径')

    def _add_install_common_tools_subparser(self):
        sub_parser = self.subparsers.add_parser("install-common-tools", help='安装常用模块')
        sub_parser.add_argument('hosts', help='资产主机组-资产清单中维护')
        sub_parser.add_argument('--inventory', default=INVENTORY_FILE, help='指定inventory文件路径')

    def _add_install_firewalld_subparser(self):
        sub_parser = self.subparsers.add_parser("install-firewalld", help='安装防火墙firewalld模块')
        sub_parser.add_argument('hosts', help='资产主机组-资产清单中维护')
        sub_parser.add_argument('--inventory', default=INVENTORY_FILE, help='指定inventory文件路径')

    def _add_install_docker_subparser(self):
        sub_parser = self.subparsers.add_parser("install-docker", help='安装Docker模块')
        sub_parser.add_argument('hosts', help='资产主机组-资产清单中维护')
        sub_parser.add_argument('--DOCKER_DATA_ROOT_DIR', help='指定Docker数据存储目录')
        sub_parser.add_argument('--inventory', default=INVENTORY_FILE, help='指定inventory文件路径')

    def _add_install_jdk8_subparser(self):
        sub_parser = self.subparsers.add_parser("install-jdk8", help='安装jdk8模块')
        sub_parser.add_argument('hosts', help='资产主机组-资产清单中维护')
        sub_parser.add_argument('--OPT_ROOT_PATH', help='指定jdk安装目录')
        sub_parser.add_argument('--inventory', default=INVENTORY_FILE, help='指定inventory文件路径')

    def _add_install_repo_subparser(self):
        sub_parser = self.subparsers.add_parser("install-yumrepo", help='安装yum源模块，常用模块（快速）')
        sub_parser.add_argument('hosts', help='资产主机组-资产清单中维护')
        sub_parser.add_argument('--inventory', default=INVENTORY_FILE, help='指定inventory文件路径')

    def _add_install_repo_manager_subparser(self):
        sub_parser = self.subparsers.add_parser("install-repo-manager", help='安装包管理工具源模块，注意：使用前需先配置好资产清单文件中的repo_source组')
        sub_parser.add_argument('hosts', help='资产主机组-资产清单中维护')
        sub_parser.add_argument('--inventory', default=INVENTORY_FILE, help='指定inventory文件路径')

    
    def _add_install_mydumper_subparser(self):
        sub_parser = self.subparsers.add_parser("install-mydumper", help='安装MyDumper模块')
        sub_parser.add_argument('hosts', help='资产主机组-资产清单中维护')
        sub_parser.add_argument('--inventory', default=INVENTORY_FILE, help='指定inventory文件路径')


    def _add_install_nginx_subparser(self):
        sub_parser = self.subparsers.add_parser("install-nginx", help='安装Nginx模块')
        sub_parser.add_argument('hosts', help='资产主机组-资产清单中维护')
        sub_parser.add_argument('--inventory', default=INVENTORY_FILE, help='指定inventory文件路径')

    def _add_firewall_whitelist_subparser(self):
        sub_parser = self.subparsers.add_parser("firewall-whitelist", help='防火墙白名单互信模块')
        sub_parser.add_argument('hosts', help='资产主机组-资产清单中维护')
        sub_parser.add_argument('--inventory', default=INVENTORY_FILE, help='指定inventory文件路径')


        
    def _add_config_yumrepo_subparser(self):
        sub_parser = self.subparsers.add_parser("config-yumrepo", help='配置yum源模块')
        sub_parser.add_argument('hosts', help='资产主机组-资产清单中维护')
        sub_parser.add_argument('--inventory', default=INVENTORY_FILE, help='指定inventory文件路径')
    
    def _add_config_repo_subparser(self):
        sub_parser = self.subparsers.add_parser("config-repo", help='配置包管理工具源模块')
        sub_parser.add_argument('hosts', help='资产主机组-资产清单中维护')
        sub_parser.add_argument('--inventory', default=INVENTORY_FILE, help='指定inventory文件路径')



    def _add_test_subparser(self):
        sub_parser = self.subparsers.add_parser("test", help='test测试模块')
        sub_parser.add_argument('hosts', help='资产主机组-资产清单中维护')
        # sub_parser.add_argument('--alias_hosts_domain', help='Specify the name of the repository to install', nargs='+', action="extend")
        sub_parser.add_argument('--DOCKER_DATA_ROOT_DIR', help='指定Docker数据存储目录')
        sub_parser.add_argument('--inventory', default=INVENTORY_FILE, help='指定inventory文件路径')

    def _add_test_inner_subparser(self):
        sub_parser = self.subparsers.add_parser("test-inner", help='test测试模块')
        sub_parser.add_argument('hosts', help='资产主机组-资产清单中维护')
        # sub_parser.add_argument('--alias_hosts_domain', help='Specify the name of the repository to install', nargs='+', action="extend")
        sub_parser.add_argument('--DOCKER_DATA_ROOT_DIR', help='指定Docker数据存储目录')
        sub_parser.add_argument('--inventory', default=INVENTORY_FILE, help='指定inventory文件路径')


    def _add_sync_time_subparser(self):
        sub_parser = self.subparsers.add_parser("sync-time", help='同步服务器时间模块')
        sub_parser.add_argument('hosts', help='资产主机组-资产清单中维护')
        sub_parser.add_argument('--time_server_host', help='时间服务器ip地址，默认为主机清单中time-server01')
        sub_parser.add_argument('--inventory', default=INVENTORY_FILE, help='指定inventory文件路径')



    def run(self):
        """
        处理模块
        """
        args = self.parser.parse_args()

        args_dict = vars(args).copy() 
        args_dict.pop("hosts", None)
        args_dict.pop("module", None)
        args_dict.pop("inventory", None)

        # 要收集facts的列表
        # facts_list = ['download-file', 'config-yumrepo', 'install-docker', 'test', 'firewall-whitelist']
        # self._handle_module(args.module, args.hosts, args_dict, 'yes' if args.module in facts_list else 'no')
        self._handle_module(args.module, args.hosts, args_dict, 'yes')

        # 执行剧本
        self.generator.run_playbook(args.inventory)

    def _handle_module(self, module, hosts, args_dict, gather_facts='no'):
        self.generator.generate_playbook_file(self.generator.generate_playbook(role=module, hosts=hosts, gather_facts=gather_facts, **args_dict))



if __name__ == '__main__':
    tool = CommandTool()
    tool.run()
